home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / Classes / IEMappedFile / IEMappedFile.m < prev    next >
Text File  |  1995-06-12  |  3KB  |  179 lines

  1. // IEMappedFile.m by Monty Zukowski 1/21/93 version 1.0
  2. //Copyright 1993 Intuitive Edge
  3. //You are free to use and modify this as long as you acknowledge me in your 
  4. //program somewhere
  5.  
  6. #import"IEMappedFile.h"
  7. #import<objc/HashTable.h>
  8. #import<objc/hashtable.h>
  9. #import <libc.h>
  10.  
  11. @implementation IEMappedFile
  12.  
  13. static HashTable *hash=nil;
  14.  
  15. +_removeFromHashTable:(IEMappedFile *)obj
  16. {
  17.     [hash removeKey:[obj name]];
  18.     return self;
  19. }
  20.  
  21. +_addName:(NXAtom) theName andObject:obj
  22. {//returns nil if name is already in the table, otherwise
  23.     // it puts name and obj in the table and returns self.
  24.     if (!hash)
  25.         hash=[[HashTable alloc] initKeyDesc:"%" valueDesc:"@"];
  26.     if (![hash valueForKey:theName])
  27.     {
  28.         [hash insertKey: theName value:obj];
  29.         return self;
  30.     }
  31.     else
  32.         return nil;
  33. }
  34.  
  35. +(HashTable *) instances    {    return hash;    }
  36.  
  37. +newForFilename:(const char *) filename
  38. {
  39.     NXAtom theAtom=NXUniqueString(filename);
  40.     IEMappedFile *instance;
  41.     
  42.     if (!hash)
  43.         hash=[[HashTable alloc] initKeyDesc:"%" valueDesc:"@"];
  44.     if (instance=[hash valueForKey:theAtom])
  45.         return instance;
  46.     else
  47.     {
  48.         instance=[super new];
  49.         instance->name=theAtom;
  50.         if ([instance _initFromName])
  51.         {
  52.             [hash insertKey:theAtom value:instance];
  53.             return instance;
  54.         }
  55.         else
  56.         {
  57.             [instance free];
  58.             return nil;
  59.         }
  60.     }
  61. }
  62.  
  63. -free
  64. {
  65.     [IEMappedFile _removeFromHashTable:self];
  66.     if (fd>=0)
  67.         close(fd);
  68.     return [super free];
  69. }
  70.  
  71. -(const void *) data    {    return data;    }
  72.  
  73. -(const void *) dataUpdated
  74. {
  75.     struct stat sbuf;
  76.     
  77.     if (fd>=0)
  78.     {
  79.         if (fstat(fd,&sbuf)!=0)  //!=0 means fstat failed
  80.         {
  81.             [self _inactivate];
  82.         }
  83.         else
  84.             if (sbuf.st_mtime!=lastModifyTime)
  85.             {
  86.                 [self _initFromName];
  87.             }
  88.     }
  89.     else 
  90.     {    //fd was invalid, see if it is fixed now
  91.         [self _initFromName];
  92.     }
  93.     return data;
  94. }
  95.  
  96. -(int) fd    {    return fd;    }
  97.  
  98. -(int) size    {    return size;    }
  99.  
  100. -(NXAtom) name    {    return name;    }
  101.  
  102. -(time_t) lastModifyTime    {    return lastModifyTime;    }
  103.  
  104.  
  105. -write:(NXTypedStream *) typedStream
  106. {
  107.     [super write:typedStream];
  108.     NXWriteType(typedStream,"%",&name);
  109.     return self;
  110. }
  111.  
  112. -read:(NXTypedStream *) typedStream
  113. {
  114.     NXReadType(typedStream,"%",&name);
  115.     [self _initFromName];
  116.     return self;
  117. }
  118.  
  119. -finishUnarchiving
  120. {
  121. /* This is needed to guarantee that if an IEMappedFile object gets archived
  122.     more than once, on unarchiving there will still only be one object per
  123.     filename.
  124. */
  125.  
  126.     if ([IEMappedFile _addName:name andObject:self])
  127.         return nil;//returning nil means ok to use self, see Object docs
  128.     else
  129.     {//dont use [self free] because it would remove the name from the hashtable
  130.         NXAtom theName=[self name];
  131.         if (fd>=0)
  132.             close(fd);
  133.         [super free];
  134.         return [IEMappedFile newForFilename:theName];
  135.     }
  136. }
  137.  
  138. -_initFromName
  139. {//returns self if successful, nil otherwise
  140.     struct stat    sbuf;
  141.         
  142.     if (stat(name,&sbuf)==0)
  143.     {
  144.         if ((fd=open(name,O_RDONLY,0444))>=0)
  145.         {
  146.             if (map_fd(fd,(vm_offset_t) 0, &(vm_offset_t)data,TRUE,
  147.                     (vm_size_t) sbuf.st_size) == KERN_SUCCESS)
  148.             {
  149.                 size=sbuf.st_size;
  150.                 lastModifyTime=sbuf.st_mtime;
  151.             }
  152.             else
  153.             {    //map_fd failed
  154.                 [self _inactivate];
  155.                 return nil;
  156.             }
  157.         }
  158.         else
  159.         {    //couldn't open() name
  160.             [self _inactivate];
  161.             return nil;
  162.         }
  163.     }
  164.     else    //couldn't stat name
  165.     {
  166.         [self _inactivate];
  167.         return nil;
  168.     }
  169.     return self;
  170. }
  171. -_inactivate
  172. {
  173.     fd = -1;
  174.     size = 0;
  175.     data = NULL;
  176.     lastModifyTime = 0;
  177.     return self;
  178. }
  179. @end